package com.yuma.tingshu.order.template;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yuma.tingshu.common.constant.RedisConstant;
import com.yuma.tingshu.common.constant.SystemConstant;
import com.yuma.tingshu.common.execption.YumaException;
import com.yuma.tingshu.common.result.ResultCodeEnum;
import com.yuma.tingshu.order.helper.SignHelper;
import com.yuma.tingshu.vo.order.OrderInfoVo;
import com.yuma.tingshu.vo.order.TradeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;

// 创建一个抽象的父类
@Component
public abstract class TradeTemplate {

    @Autowired
    private RedisTemplate redisTemplate;

    // 定义正常方法，返回值
    public OrderInfoVo trade(TradeVo tradeVo) {
        // 1.创建OrderInfoVo对象
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 2.参数判空
        if (tradeVo == null || tradeVo.getItemType() == null || tradeVo.getItemId() == null) {
            throw new YumaException(ResultCodeEnum.ARGUMENT_VALID_ERROR);
        }
        // 3.初始设置订单信息的交易号，支付方式，订单类型，支付状态
        orderInfoVo.setTradeNo(IdWorker.getIdStr());// 主键自增策略
        orderInfoVo.setPayWay(SystemConstant.ORDER_PAY_WAY_WEIXIN);
        orderInfoVo.setItemType(tradeVo.getItemType());

        // 调用抽象方法
        buildOrderInfoVo(orderInfoVo, tradeVo);

        // 10.设置时间戳，创建签名，并设置签名
        orderInfoVo.setTimestamp(SignHelper.getTimestamp());
        // 10.1先把orderInfoVo对象转换成json
        String orderInfoVoJson = JSON.toJSONString(orderInfoVo);
        // 10.2把json转换成HashMap
        Map<String, Object> orderInfoVoMap = JSON.parseObject(orderInfoVoJson, Map.class);
        // 10.3把HashMap转换成Sign
        // sign = TradeNo|PayWay|ItemType|Timestamp
        orderInfoVo.setSign(SignHelper.getSign(orderInfoVoMap));

        // 11. 为了提交订单的幂等性，写入redis中一个订单号
        redisTemplate.opsForValue().set(RedisConstant.ORDER_IDEM_PREFIX + orderInfoVo.getTradeNo(), "1",
                1, TimeUnit.DAYS);

        // 11.返回订单对象
        return orderInfoVo;
    }

    // 抽象方法（订单生成子类去实现）
    public abstract void buildOrderInfoVo(OrderInfoVo orderInfoVo, TradeVo tradeVo);
}
